13. Using Idling Resources
L5 P4 A11 Using Idling Resources V2
In this step, you'll use your two idling resources to make your TasksActivityTest end-to-end tests run deterministically.
Step 1: Use Idling Resources in Tests
- Open TasksActivityTest.kt.
- Instantiate a
private DataBindingIdlingResource:
TasksActivityTest.kt
// An idling resource that waits for Data Binding to have no pending bindings.
private val dataBindingIdlingResource = DataBindingIdlingResource()
- Create
@Beforeand@Aftermethods that register and unregister theEspressoIdlingResource.countingIdlingResourceanddataBindingIdlingResource:
TasksActivityTest.kt
/**
* Idling resources tell Espresso that the app is idle or busy. This is needed when operations
* are not scheduled in the main Looper (for example when executed on a different thread).
*/
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
IdlingRegistry.getInstance().register(dataBindingIdlingResource)
}
/**
* Unregister your Idling Resource so it can be garbage collected and does not leak any memory.
*/
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
IdlingRegistry.getInstance().unregister(dataBindingIdlingResource)
}
- Update the
editTask()test so that after you launch the activity scenario, you usemonitorActivityto associate the activity with thedataBindingIdlingResource:
TasksActivityTest.kt
@Test
fun editTask() = runBlocking {
repository.saveTask(Task("TITLE1", "DESCRIPTION"))
// Start up Tasks screen.
val activityScenario = ActivityScenario.launch(TasksActivity::class.java)
dataBindingIdlingResource.monitorActivity(activityScenario) // LOOK HERE
// Rest of test...
}
- Run your test five times. You should find that the test is no longer flaky.
The entire TasksActivityTest should look like this:
TasksActivityTest.kt
@RunWith(AndroidJUnit4::class)
@LargeTest
class TasksActivityTest {
private lateinit var repository: TasksRepository
// An idling resource that waits for Data Binding to have no pending bindings.
private val dataBindingIdlingResource = DataBindingIdlingResource()
@Before
fun init() {
repository =
ServiceLocator.provideTasksRepository(
getApplicationContext()
)
runBlocking {
repository.deleteAllTasks()
}
}
@After
fun reset() {
ServiceLocator.resetRepository()
}
/**
* Idling resources tell Espresso that the app is idle or busy. This is needed when operations
* are not scheduled in the main Looper (for example when executed on a different thread).
*/
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
IdlingRegistry.getInstance().register(dataBindingIdlingResource)
}
/**
* Unregister your Idling Resource so it can be garbage collected and does not leak any memory.
*/
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
IdlingRegistry.getInstance().unregister(dataBindingIdlingResource)
}
@Test
fun editTask() = runBlocking {
// Set initial state.
repository.saveTask(Task("TITLE1", "DESCRIPTION"))
// Start up Tasks screen.
val activityScenario = ActivityScenario.launch(TasksActivity::class.java)
// Click on the task on the list and verify that all the data is correct.
onView(withText("TITLE1")).perform(click())
onView(withId(R.id.task_detail_title_text)).check(matches(withText("TITLE1")))
onView(withId(R.id.task_detail_description_text)).check(matches(withText("DESCRIPTION")))
onView(withId(R.id.task_detail_complete_checkbox)).check(matches(not(isChecked())))
// Click on the edit button, edit, and save.
onView(withId(R.id.edit_task_fab)).perform(click())
onView(withId(R.id.add_task_title_edit_text)).perform(replaceText("NEW TITLE"))
onView(withId(R.id.add_task_description_edit_text)).perform(replaceText("NEW DESCRIPTION"))
onView(withId(R.id.save_task_fab)).perform(click())
// Verify task is displayed on screen in the task list.
onView(withText("NEW TITLE")).check(matches(isDisplayed()))
// Verify previous task is not displayed.
onView(withText("TITLE1")).check(doesNotExist())
// Make sure the activity is closed before resetting the db.
activityScenario.close()
}
}
Step 2: Write your own test with idling resources
Now it's your turn.
- Copy over the following code:
TasksActivityTest.kt
````
@Test
fun createOneTask_deleteTask() {
// 1. Start TasksActivity.
// 2. Add an active task by clicking on the FAB and saving a new task.
// 3. Open the new task in a details view.
// 4. Click delete task in menu.
// 5. Verify it was deleted.
// 6. Make sure the activity is closed.
}
```
- Finish the code, referring to the
editTasktest you added previously. - Run your test and confirm it passes!
The completed test is here so you can compare.